aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/envshare/pages/api/v1/secret/[id].ts
blob: 8b5f08295e061a5373a570892901d8562d4b4eea (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import { NextRequest, NextResponse } from "next/server";
import { Redis } from "@upstash/redis";
import { z } from "zod";

const responseValidation = z.union([
  z.object({
    data: z.object({
      remainingReads: z.number().int().optional(),
      secret: z.string(),
    }),
  }),
  z.object({
    error: z.string(),
  }),
]);

const redis = Redis.fromEnv();
export default async function handler(req: NextRequest): Promise<NextResponse> {
  try {
    if (req.method !== "GET") {
      return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
    }
    const id = new URL(req.url).searchParams.get("id");
    if (!id) {
      return NextResponse.json({ error: "Missing `id` parameter" }, { status: 400 });
    }

    const redisKey = ["envshare", id].join(":");

    const [data, _] = await Promise.all([
      await redis.hgetall<{ secret: string; remainingReads: number | null }>(redisKey),
      await redis.incr("envshare:metrics:reads"),
    ]);

    if (!data) {
      return NextResponse.json({ error: "Not Found" }, { status: 404 });
    }
    if (data.remainingReads !== null && data.remainingReads < 1) {
      await redis.del(redisKey);
      return NextResponse.json({ error: "Not Found" }, { status: 404 });
    }

    let remainingReads: number | null = null;
    if (data.remainingReads !== null) {
      // Decrement the number of reads and return the remaining reads
      remainingReads = await redis.hincrby(redisKey, "remainingReads", -1);
    }

    return NextResponse.json({ data: { secret: data.secret, remainingReads: remainingReads ?? undefined } });
  } catch (e) {
    console.error(e);
    return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
  }
}

export const config = {
  runtime: "edge",
};